package icasue.tools.sqlhelper.core;

import icasue.tools.sqlhelper.core.DBTab;
import icasue.tools.sqlhelper.core.Frame;
import icasue.reflect.annotations.NotNull;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

/**
 * @Author: Qiao Hang
 * @CreateDate: 2021/9/26 下午5:24
 * @UpdateDate:
 * @Description:
 */
public abstract class AbstractSqlProviderFrame<JavaType,ColMark extends Annotation> {

    /**
     * 存储标记的数据库字段映射类型
     */
    @NotNull
    protected final Class<ColMark> markedAnnotationType;

    /**
     * 存储数据库表映射的JavaType.
     */
    @NotNull
    protected final Class<JavaType> javaType;

    /**
     * 存储数据库表映射, 表上的聚簇索引映射，列与java属性的映射.
     */
    @NotNull protected final DBTab dbTab;

    protected AbstractSqlProviderFrame(Class<JavaType> javaType, Class<ColMark> colMark){
        this.javaType = javaType;
        this.markedAnnotationType = colMark;
        this.dbTab = Frame._init(this);
    }

    public AbstractSqlProviderFrame(){
        Class[] typeArguments = Frame._parse(this);
        this.javaType = (Class<JavaType>) typeArguments[0];
        this.markedAnnotationType = (Class<ColMark>) typeArguments[1];
        this.dbTab = Frame._init(this);
    }

    /**
     * 抽象获取数据库路由接口.
     * @return database for routing.
     */
    protected abstract String database();

    /**
     * 抽象获取表路由接口.
     * @return table for routing.
     */
    protected abstract String table();

    /**
     * 是否递归去获取属性数据库映射.
     * @return
     */
    protected abstract boolean recursionDiscoveryFields();

    /**
     * 如果存在MarkAnnotation映射关系时，列映射的方式方法，
     * 实际为ColMark注解的某一方法, 该方法存在的意义就是描述
     * JavaType与DBCol的映射关系，所描述的方法需返回 java.lang.String.
     * @param markAnnotation
     * @return column for routing.
     */
    protected abstract String mappingOnMarkAnnotation(@NotNull Field jField,
                                                      @NotNull ColMark markAnnotation);


    /**
     * 配置JavaField映射到数据库Column的映射关系.
     * @param jField 成员属性
     * @param fName 属性名称
     * @param fJavaType 属性的Java类型
     * @param nativeTo 属性所处的类元素
     * @return null or mapped column name, if return null,
     * this filed will be ignore to create mapping.
     */
    protected String mappingOnLackMarkAnnotation(@NotNull Field jField,
                                                 @NotNull String fName,
                                                 @NotNull Class fJavaType,
                                                 @NotNull Class nativeTo){
        /* perhaps filter JavaField is suitable for create mapping...
            filter: true / false. */

        // create mapping, by default all field which touchable will been creating mapping relationship.
        return Frame.$defaultMapping.apply(jField);
    };


}
